﻿/*
 * BlockBitmapSource
 * 
 * initial implementation : 3.12.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;

namespace Petra.Gis.ImagingServices.Tiff
{

  /// <summary>
  /// represents tiff BitmapSource with specific memory storage format, 
  /// metadata and pixel manipulation
  /// tiff support various pixel formats and various compressions
  /// </summary>
  public partial class BlockBitmapSource : BitmapSource
  {

    protected TiffReader _tiffReader;
    protected BitmapCreateOptions _createOptions;

    protected BlockBitmapSource(TiffReader tiffReader, ImageFileDirectory ifd, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption)
    {

      _tiffReader = tiffReader;
      
      // create metadata
      _metadata = new Metadata(ifd);

      if (createOptions == BitmapCreateOptions.PreservePixelFormat)
        _decodeBilevelAs8bpp = false;
      else
        _decodeBilevelAs8bpp = true;

      _createOptions = createOptions;
      this.BitmapCacheOption = cacheOption;

      // prepare compression
      _fileDataCompression = TiffBitmapDecoder.GetCompression(_metadata.Compression);

      // prepare tiff blocks
      _blocks = new BitmapBlocks(this, null);
    }


    #region BitmapSource Properties




    protected bool _decodeBilevelAs8bpp;


    public bool DecodeBilevelAs8bpp
    {
      get { return _decodeBilevelAs8bpp; }
    }






    public TiffReader DataReader
    {
      get { return _tiffReader; }
    }



    protected BitmapBlocks _blocks;

    /// <summary>
    /// reference to all blocks of current Page/Frame
    /// </summary>
    public BitmapBlocks Blocks
    {
      get
      {
        return _blocks;
      }
    }





    protected Compression _fileDataCompression;


    public Compression Compression
    {
      get { return _fileDataCompression; }
    }





    /// <summary>
    ///     Horizontal DPI of the bitmap.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override double DpiX
    {
      get
      {
        return 96.0;
      }
    }






    /// <summary>
    ///     Vertical DPI of the bitmap.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override double DpiY
    {
      get
      {
        return (double)96.0;
      }
    }





    /// <summary>
    ///     Pixel format of the bitmap.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override PixelFormat Format
    {
      get
      {
        if (this.DecodeBilevelAs8bpp && _metadata.MapPixelFormat() == PixelFormats.BlackWhite)
          return PixelFormats.Indexed8;
        else
          return _metadata.MapPixelFormat();
      }
    }






    /// <summary>
    ///     Width of the bitmap contents.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override int PixelWidth
    {
      get
      {
        return _metadata.Width;
      }
    }
    




    /// <summary>
    ///     Height of the bitmap contents.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override int PixelHeight
    {
      get
      {
        return _metadata.Height;
      }
    }





    /// <summary>
    ///     Palette of the bitmap.
    /// </summary>
    /// <remarks>
    ///     Derived classes can override this to specify their own value.
    /// </remarks>
    public override BitmapPalette Palette
    {
      get
      {
        if (_metadata.IsColorMapImage())
          return new BitmapPalette(_metadata.ColorMap);

        else if (_metadata.PixelFormat == TiffPixelFormats.Bilevel1bpp && this.DecodeBilevelAs8bpp)
        {
          List<Color> tmpColorList = new List<Color>();
          tmpColorList.Add(Color.FromArgb(0, 0, 0, 0));

          //put some gray colors between...
          for (int i = 1; i < 255; i++)
            tmpColorList.Add(Color.FromArgb(255, 128, 128, 128));

          tmpColorList.Add(Color.FromArgb(255, 255, 255, 255));

          return new BitmapPalette(tmpColorList);
        }
        else
          return null;
      }
    }





    protected Metadata _metadata;


    /// <summary>
    /// returns image file directory of current frame/page
    /// </summary>
    public Metadata TiffMetadata
    {
      get { return _metadata; }
    }



    internal BitmapCacheOption BitmapCacheOption;


    //public BitmapCacheOption BlockBitmapCacheOption
    //{
    //  get { return _cacheOption; }
    //  //set { _cacheOption = value ; }
    //}



    #endregion BitmapSource Properties


    #region BitmapSource Download


    /// <summary>
    ///     Whether or not the BitmapSource is downloading content.
    /// </summary>
    /// <remarks>
    ///     This is not applicable to all BlockBitmapSource classes, so
    ///     the base implementation return false.
    /// </remarks>
    public override bool IsDownloading
    {
      get
      {
        return false;
      }
    }






    /// <summary>
    ///     Raised when the downloading of content is completed.
    /// </summary>
    /// <remarks>
    ///     This is not applicable to all BlockBitmapSource classes, so
    ///     the base implementation does nothing.
    /// </remarks>
    public override event EventHandler DownloadCompleted
    {
      add
      {
      }

      remove
      {
      }
    }






    /// <summary>
    ///     Raised when the downloading of content has progressed.
    /// </summary>
    /// <remarks>
    ///     This is not applicable to all BlockBitmapSource classes, so
    ///     the base implementation does nothing.
    /// </remarks>
    public override event EventHandler<DownloadProgressEventArgs> DownloadProgress
    {
      add
      {
      }

      remove
      {
      }
    }






    /// <summary>
    ///     Raised when the downloading of content has failed.
    /// </summary>
    /// <remarks>
    ///     This is not applicable to all BlockBitmapSource classes, so
    ///     the base implementation throws.
    /// </remarks>
    public override event EventHandler<ExceptionEventArgs> DownloadFailed
    {
      add
      {
      }

      remove
      {
      }
    }
    #endregion BitmapSource Download


    #region BitmapSource Decode





    /// <summary>
    ///     Raised when the downloading of content has progressed.
    /// </summary>
    /// <remarks>
    ///     This is not applicable to all BlockBitmapSource classes, so
    ///     the base implementation does nothing.
    /// </remarks>
    public override event EventHandler<ExceptionEventArgs> DecodeFailed
    {
      add
      {
      }

      remove
      {
      }
    }


    #endregion BitmapSource Decode


  }
}
